package com.tvunetworks.center.user.resolver;

import com.tvunetworks.center.common.annotation.FetchType;
import com.tvunetworks.center.common.constant.LocalConstant;
import com.tvunetworks.center.common.exception.NoLoginException;
import com.tvunetworks.center.common.exception.SessionExpireException;
import com.tvunetworks.center.common.model.LoginUser;
import com.tvunetworks.center.common.util.Result;
import com.tvunetworks.center.common.util.ResultUtil;
import com.tvunetworks.center.user.annotation.Logined;
import com.tvunetworks.center.user.service.UserService;
import com.tvunetworks.center.user.util.GetSessionUtils;
import com.tvunetworks.center.user.util.RedisUtil;
import org.apache.commons.lang.StringUtils;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Objects;

/**
 * @program: tvucc-aggregator
 * @description:
 * @author lebronchen
 * @create: 2021-03-31 13:00
 **/
public class LoginedNullableArgumentResolver implements HandlerMethodArgumentResolver {

    private RedisUtil redisUtil;

    private UserService userService;



    public LoginedNullableArgumentResolver(RedisUtil redisUtil, UserService userService) {
        this.redisUtil = redisUtil;
        this.userService = userService;
    }

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        // 如果该参数注解有@Logined
        if (parameter.getParameterAnnotation(Logined.class) != null
                && parameter.getParameterType() == LoginUser.class) {
            // 支持解析该参数
            return true;
        }
        return false;
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
                                  NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws IOException {

     /*   ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();*/
        HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest();
        String accessToken = GetSessionUtils.getToken(request);
      //  String accessToken = request.getHeader(LocalConstant.ACCESS_TOKEN_KEY);



        // 如果用户为null，并且还检查不允许为 null 则抛出未登陆异常
        if (StringUtils.isEmpty(accessToken)) {
            if( Objects.requireNonNull(parameter.getParameterAnnotation(Logined.class)).check()){
                throw new NoLoginException("Annotation interceptor token is empty");
            } else {
                return null;
            }
        }


        LoginUser loginUser = null;

        Logined parameterAnnotation = parameter.getParameterAnnotation(Logined.class);

        if(parameterAnnotation == null){
            return null;
        }

        // Fetch from cache only
        if (FetchType.CACHE.equals(parameterAnnotation.fetch()) ) {
            loginUser = (LoginUser) redisUtil.get(LocalConstant.REDIS_LOGIN_USER_KEY + accessToken);
        } else if ( FetchType.CACHE_API.equals(parameterAnnotation.fetch()) ) {
            // Fetch from Cache first
            loginUser = (LoginUser) redisUtil.get(LocalConstant.REDIS_LOGIN_USER_KEY + accessToken);

            if(loginUser == null){
                // Fetch from api second
                Result<LoginUser> loginUserWithNoCheck = userService.getLoginUserWithNoCheck(accessToken);

                if(StringUtils.equals(ResultUtil.SUCCESS,loginUserWithNoCheck.getErrorCode())){
                    loginUser = loginUserWithNoCheck.getResult();
                }

            }

        } else if (FetchType.API.equals(parameterAnnotation.fetch()) ){

            // Fetch from api only
            Result<LoginUser> loginUserWithNoCheck = userService.getLoginUserWithNoCheck(accessToken);

            if(StringUtils.equals(ResultUtil.SUCCESS,loginUserWithNoCheck.getErrorCode())){
                loginUser = loginUserWithNoCheck.getResult();
            }
        }

//        loginUser = (LoginUser) redisUtil.get(LocalConstant.REDIS_LOGIN_USER_KEY + accessToken);

        // 如果用户为null，并且还检查不允许为 null 则抛出未登陆异常
        if (loginUser == null && parameterAnnotation.check() ) {
            throw new SessionExpireException("Annotation interceptor session expire");
        }

        return loginUser;
    }

}
